<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, minimal-ui" />

        <title>File Manager</title>

        <script src="/js/greyspots.js" type="text/javascript"></script>
        <link href="/css/greyspots.css" type="text/css" rel="stylesheet" />

        <script>
            //jslint white:true browser:true multivar:true
            var arrCurrentPath = [],
                arrCheckedPaths = [],
        		arrCheckedPathTypes = [];

            var bolWebSocket;

            // update the querystring with the latest paths
            function updateQueryString() {
                "use strict";
                var strQueryString = '', strPath;

                strPath = arrCurrentPath.join('/');
                strQueryString = 'path=' + encodeURIComponent(strPath);

                GS.pushQueryString(strQueryString);
            }

            // order checked files and folders in the correct manner (to prevent errors)
            //      Example: lets say that we must remove 2 folders and one file (in that order)
            //          rm all/
            //          rm all/bar/       <== ERROR! folder "all" does not exist
            //          rm all/test.txt   <== ERROR! folder "all" does not exist
            //
            //      Solution: order files first then folder paths with the most slashes first
            //          rm all/test.txt
            //          rm all/bar/
            //          rm all/
            //
            // this function takes a list of files/folders and sorts it in the aforementioned order
            //      then returns the combined array of the files and folders
            function sortPathArraysInOperationOrder(arrFiles, arrFolders) {
                'use strict';

                // sort folders by number of slashes (greatest number of slashes to least number of slashes)
                arrFolders.sort(function(a, b) {
                    return (b.match(/\//g) || '').length - (a.match(/\//g) || '').length;
                });

                return arrFiles.concat(arrFolders);
            }

            // prefix a file name with the current directory path
            function filePathPrefix(strFileName) {
                'use strict';
                return (arrCurrentPath.length > 0 ? arrCurrentPath.join('/') + '/' : '') + strFileName;
            }

            // sort checked array
            function getCheckedInOrder() {
                'use strict';
                var i, len, arrFiles = [], arrFolders = [];

                // seperate files and folders
                for (i = 0, len = arrCheckedPaths.length; i < len; i += 1) {
                    if (arrCheckedPathTypes[i] === 'file') {
                        arrFiles.push(arrCheckedPaths[i]);
                    } else {
                        arrFolders.push(arrCheckedPaths[i]);
                    }
                }

                return sortPathArraysInOperationOrder(arrFiles, arrFolders);
            }

            // handle toolbars disabling/enabling/clearing based on the number of checked off paths
            function handleToolbar() {
                if (arrCurrentPath.length === 0 || (arrCurrentPath.length === 1 && arrCurrentPath[0] === '')) {
                    document.getElementById('button-top').setAttribute('disabled', '');
                    document.getElementById('button-up').setAttribute('disabled', '');
                } else {
                    document.getElementById('button-top').removeAttribute('disabled');
                    document.getElementById('button-up').removeAttribute('disabled');
                }

                if (arrCheckedPaths.length > 0) {
                    if (!evt.touchDevice) {
                        document.getElementById('button-zip').removeAttribute('disabled');
                    }
                    document.getElementById('button-move').removeAttribute('disabled');
                    document.getElementById('button-rename').removeAttribute('disabled');
                    document.getElementById('button-copy').removeAttribute('disabled');
                    document.getElementById('button-delete').removeAttribute('disabled');
                    document.getElementById('button-checked').removeAttribute('disabled');
                } else {
                    document.getElementById('button-zip').setAttribute('disabled', '');
                    document.getElementById('button-move').setAttribute('disabled', '');
                    document.getElementById('button-rename').setAttribute('disabled', '');
                    document.getElementById('button-copy').setAttribute('disabled', '');
                    document.getElementById('button-delete').setAttribute('disabled', '');
                    document.getElementById('button-checked').setAttribute('disabled', '');
                    document.getElementById('current-action-container').innerHTML = '';
                }

                if (bolWebSocket) {
                    document.getElementById('button-zip').setAttribute('disabled', '');
                }
            }

            // refresh header path
            function handleHeaderText() {
                document.getElementById('current-path').textContent = filePathPrefix('') || '/';
            }

            function folderLineHTML(strTitle, strNavigateLink) {
                return '<div flex-horizontal flex-fill link="' + encodeHTML(strNavigateLink) + '">' +
                                '<gs-checkbox inline type="folder" ' +
                                        (arrCheckedPaths.indexOf(strNavigateLink) >= 0 ? 'value="true"' : '') +
                                    '></gs-checkbox>' +
                                '<gs-button class="folder" flex>' + encodeHTML(strTitle) + '</a>' +
                            '</div> ';
            }

            function fileLineHTML(strTitle, strAnchorPath, strCurrentPath) {
                var strHTML = '';

                if (strAnchorPath.indexOf('/') === 0) {
                    strAnchorPath = strAnchorPath.substring(1);
                }

                if (strAnchorPath.indexOf('app/') == 0) {
                    strAnchorPath = '/env/' + strAnchorPath;

                } else if (strAnchorPath.indexOf('role/') == 0) {
                    strAnchorPath = '/env/' + strAnchorPath;

                } else if (strAnchorPath.indexOf('web_root/') == 0) {
                    strAnchorPath = strAnchorPath.substring(8);
                } else {
                    strAnchorPath = '/' + strAnchorPath;
                }

                strHTML += '<div flex-horizontal flex-fill link="' + strCurrentPath + '">' +
                    '<gs-checkbox inline type="file" ' +
					(arrCheckedPaths.indexOf(strCurrentPath) >= 0 ? 'value="true"' : '') +
					'></gs-checkbox>';

                if (strCurrentPath.toLowerCase().indexOf('.zip') === strCurrentPath.length - 4) {
                    if (!bolWebSocket) {
                        strHTML += '<gs-button onclick="unzipFile(\'' + strCurrentPath +
    						'\')" icononly icon="expand" remove-right remove-margin-right></gs-button>';
                    }
                } else {
                    strHTML += '<gs-button remove-margin-right "target="_blank" href="file_edit.html?' +
                        (bolWebSocket === true ? 'socket=true&' : '') +
                        'link=' + encodeURIComponent(strCurrentPath) +
                		'" icononly icon="pencil" remove-right></gs-button>';
                }

                strHTML += '<gs-button flex href="' + encodeHTML(strAnchorPath) +
					'" target="_blank" class="file" ' + (strCurrentPath.toLowerCase().indexOf('.zip') === strCurrentPath.length - 4 && bolWebSocket ? '' : 'remove-left remove-margin-left') + '>' + encodeHTML(strTitle) + '</gs-button>' +
                    '</div>';

                return strHTML;
            }

            // get/refresh the list of files and folders for the current path
            function listCurrentDirectory() {
                'use strict';
                var strPath;

                // handle toolbars disabled/clearing and handle header text
                handleToolbar();
                handleHeaderText();

                strPath = arrCurrentPath.join('/');

                if (bolWebSocket) {
                    // list files/folders WS style
                    GS.addLoader('file-list-load', 'Loading...');

                    var arrFile = [], arrFolder = [];
                    GS.requestFromSocket(GS.envSocket, 'FILE\tLIST\t' + GS.encodeForTabDelimited(strPath), function (data, error, errorData) {
                        var arrPaths, strHTML, strCurrentPath, strAnchorPath, i, len
                          , arrCells, strType, strName, strFileHTML, strFolderHTML;

                        if (!error && data.trim() && data.indexOf('Failed to get canonical path') === -1) {
                            if (data !== 'TRANSACTION COMPLETED') {
                                arrPaths = GS.trim(data, '\n').split('\n');

                                for (i = 0, len = arrPaths.length; i < len; i += 1) {
                                    arrCells = arrPaths[i].split('\t');
                                    strType = GS.decodeFromTabDelimited(arrCells[1]);
                                    strName = GS.trim(GS.decodeFromTabDelimited(arrCells[0]), '/');

                                    if (strType === 'folder') {
                                        arrFolder.push(strName);

                                    } else if (strType === 'file') {
                                        arrFile.push(strName);
                                    }
                                }

                            } else {
                                strFileHTML = '';
                                strFolderHTML = '';

                                arrFolder.sort();
                                arrFile.sort();

                                for (i = 0, len = arrFolder.length; i < len; i += 1) {
                                    strName = arrFolder[i];

                                    strCurrentPath = filePathPrefix(strName);
                                    strFolderHTML += folderLineHTML(strName, strCurrentPath);
                                }

                                for (i = 0, len = arrFile.length; i < len; i += 1) {
                                    strName = arrFile[i];

                                    strCurrentPath = filePathPrefix(strName);
                                    strAnchorPath = strCurrentPath;

                                    strFileHTML += fileLineHTML(strName, strAnchorPath, strCurrentPath);
                                }

                                strHTML  = '<h3>Folders:</h3>';
                                strHTML += strFolderHTML || '<span class="hint">No Folders.</span>';

                                strHTML += '<br />';

                                strHTML += '<h3>Files:</h3>';
                                strHTML += strFileHTML || '<span class="hint">No files.</span>';

                                document.getElementById('file-list').innerHTML = strHTML;
                                GS.removeLoader('file-list-load');
                            }
                        } else if (error) {
                            GS.removeLoader('file-list-load');
                            GS.webSocketErrorDialog(errorData, listCurrentDirectory, function () {
								console.log('test');
								arrCurrentPath.pop();
								listCurrentDirectory();
							});
                        }
                    });

                } else {
                    // list files/folders AJAX style
                    GS.addLoader('file-list-load', 'Loading...');
                    GS.ajaxJSON('/env/action_file', 'action=list' +
                                '&path=' + encodeURIComponent(strPath), function(response, error) {
                        var i, len, strHTML = '', data, strCurrentPath, strAnchorPath;

                        GS.removeLoader('file-list-load');

                        if (!error) {
                            data = response.dat;

                            data.directories = data.directories || [];
                            data.files = data.files || [];

                            data.directories.sort();
                            data.files.sort();

                            strHTML += '<h3>Folders:</h3>';
                            for (i = 0, len = data.directories.length; i < len; i += 1) {
                                strCurrentPath = filePathPrefix(data.directories[i]);

                                strHTML += folderLineHTML(data.directories[i], strCurrentPath);
                            }
                            if (data.directories.length === 0) {
                                strHTML += '<span class="hint">No Folders.</span>'
                            }

                            strHTML += '<br />';
                            strHTML += '<h3>Files:</h3>';

                            for (i = 0, len = data.files.length; i < len; i += 1) {
                                strCurrentPath = filePathPrefix(data.files[i]);
                                strAnchorPath = strCurrentPath;

                                strHTML += fileLineHTML(data.files[i], strAnchorPath, strCurrentPath);
                            }
                            if (data.files.length === 0) {
                                strHTML += '<span class="hint">No files.</span>'
                            }

                            document.getElementById('file-list').innerHTML = strHTML;
                        } else {
                            GS.ajaxErrorDialog(response, function() {
                                listCurrentDirectory();
                            }, function () {
                                arrCurrentPath.pop();
                                updateQueryString();
                                listCurrentDirectory();
                            });
                        }
                    });
                }
            }

            function unzipFile(strPath) {
                GS.addLoader('file-unzip', 'Unzipping...');
                GS.ajaxJSON('/env/action_file', 'action=unzip&path=' + encodeURIComponent(strPath),
                                                 function (data, error) {
                    GS.removeLoader('file-unzip');

                    if (!error) {
                        listCurrentDirectory();

                    } else {
                        GS.ajaxErrorDialog(data);
                    }
                });
            }

            function insertFile(strFileName) {
                'use strict';

                if (bolWebSocket) {
                    GS.requestFromSocket(GS.envSocket
                                       , 'FILE\tCREATE_FILE\t' + GS.encodeForTabDelimited(strFileName) + '\n'
                                       , function (data, error, errorData) {
                        if (!error) {
                            if (data === 'TRANSACTION COMPLETED') {
                                GS.removeLoader('file-insert');
                                arrCheckedPaths = [];
                                arrCheckedPathTypes = [];
                                listCurrentDirectory();
                            }
                        } else if (error) {
                            GS.removeLoader('file-insert');
                            GS.webSocketErrorDialog(errorData);
                        }
                    });
                } else {
                    GS.addLoader('file-insert', 'Creating File...');
                    GS.ajaxJSON('/env/action_file', 'action=create_file' +
                                '&path=' + encodeURIComponent(strFileName) + '&content=', function(data, error) {
                        GS.removeLoader('file-insert');

                        if (!error) {
                            arrCheckedPaths = [];
                            arrCheckedPathTypes = [];
                            listCurrentDirectory();

                        } else {
                            GS.ajaxErrorDialog(data, function() {
                                insertFile(strFileName);
                            });
                        }
                    });
                }
            }

            function insertFolder(strFolderName) {
                'use strict';
                if (bolWebSocket) {
                    GS.addLoader('folder-insert', 'Creating Folder...');
                    GS.requestFromSocket(GS.envSocket
                                       , 'FILE\tCREATE_FOLDER\t' + GS.encodeForTabDelimited(strFolderName) + '\n'
                                       , function (data, error, errorData) {
                        if (!error) {
                            if (data === 'TRANSACTION COMPLETED') {
                                GS.removeLoader('folder-insert');
                                arrCheckedPaths = [];
                                arrCheckedPathTypes = [];
                                listCurrentDirectory();
                            }
                        } else if (error) {
                            GS.removeLoader('folder-insert');
                            GS.webSocketErrorDialog(errorData);
                        }
                    });
                } else {
                    GS.addLoader('folder-insert', 'Creating Folder...');
                    GS.ajaxJSON('/env/action_file', 'action=create_folder' +
                                '&path=' + encodeURIComponent(strFolderName), function(data, error) {
                        GS.removeLoader('folder-insert');

                        if (!error) {
                            arrCheckedPaths = [];
                            arrCheckedPathTypes = [];
                            listCurrentDirectory();

                        } else {
                            GS.ajaxErrorDialog(data, function() {
                                insertFolder(strFolderName);
                            });
                        }
                    });
                }
            }

            function movePaths(pathsFrom, pathsTo) {
                'use strict';
                var i, len, intResponse;

                if (bolWebSocket) {
                    pathsFrom = JSON.parse(pathsFrom);
                    pathsTo = JSON.parse(pathsTo);

                    for (i = 0, len = pathsFrom.length; i < len; i += 1) {
                        GS.addLoader('file-and-folder-move', 'Moving Paths...');
                        intResponse = 0;
                        GS.requestFromSocket(GS.envSocket
                                           , 'FILE\tMOVE\t' + GS.encodeForTabDelimited(pathsFrom[i]) + '\t' +
                                                              GS.encodeForTabDelimited(pathsTo[i]) + '\n'
                                           , function (data, error, errorData) {
                            if (!error) {
                                if (data === 'TRANSACTION COMPLETED') {
                                    intResponse += 1;
                                    GS.removeLoader('file-and-folder-move');

                                    if (intResponse === len) {
                                        arrCheckedPaths = [];
                                        arrCheckedPathTypes = [];
                                        listCurrentDirectory();
                                    }
                                }
                            } else if (error) {
                                intResponse += 1;
                                GS.removeLoader('file-and-folder-move');
                                GS.webSocketErrorDialog(errorData);
                            }
                        });
                    }

                } else {
                    GS.addLoader('file-and-folder-move', 'Moving Paths...');
                    GS.ajaxJSON('/env/action_file', 'action=mv_file' +
                                                                '&paths_from=' + encodeURIComponent(pathsFrom) +
                                                                '&paths_to=' + encodeURIComponent(pathsTo), function(data, error) {
                        GS.removeLoader('file-and-folder-move');

                        if (!error) {
                            arrCheckedPaths = [];
                            arrCheckedPathTypes = [];
                            listCurrentDirectory();

                        } else {
                            GS.ajaxErrorDialog(data, function() {
                                movePaths(pathsFrom, pathsTo);
                            });
                        }
                    });
                }
            }

            function copyPaths(pathsFrom, pathsTo) {
                'use strict';
                var i, len, intResponse;

                if (bolWebSocket) {
                    pathsFrom = JSON.parse(pathsFrom);
                    pathsTo = JSON.parse(pathsTo);

                    for (i = 0, len = pathsFrom.length; i < len; i += 1) {
                        GS.addLoader('file-and-folder-copy', 'Pasting Paths...');
                        intResponse = 0;
                        GS.requestFromSocket(GS.envSocket
                                           , 'FILE\tCOPY\t' + GS.encodeForTabDelimited(pathsFrom[i]) + '\t' +
                                                              GS.encodeForTabDelimited(pathsTo[i]) + '\n'
                                           , function (data, error, errorData) {
                            if (!error) {
                                if (data === 'TRANSACTION COMPLETED') {
                                    intResponse += 1;
                                    GS.removeLoader('file-and-folder-copy');

                                    if (intResponse === len) {
                                        arrCheckedPaths = [];
                                        arrCheckedPathTypes = [];
                                        listCurrentDirectory();
                                    }
                                }
                            } else if (error) {
                                intResponse += 1;
                                GS.removeLoader('file-and-folder-copy');
                                GS.webSocketErrorDialog(errorData);
                            }
                        });
                    }

                } else {
                    GS.addLoader('file-and-folder-copy', 'Pasting Paths...');
                    GS.ajaxJSON('/env/action_file', 'action=cp_file' +
                                                                         '&paths_from=' + encodeURIComponent(pathsFrom) +
                                                                         '&paths_to=' + encodeURIComponent(pathsTo), function(data, error) {
                        GS.removeLoader('file-and-folder-copy');

                        if (!error) {
                            arrCheckedPaths = [];
                            arrCheckedPathTypes = [];
                            listCurrentDirectory();

                        } else {
                            GS.ajaxErrorDialog(data, function() {
                                copyPaths(pathsFrom, pathsTo);
                            });
                        }
                    });
                }
            }

            function renamePaths(pathsFrom, pathsTo) {
                'use strict';
                var i, len, intResponse;

                if (bolWebSocket) {
                    pathsFrom = JSON.parse(pathsFrom);
                    pathsTo = JSON.parse(pathsTo);

                    for (i = 0, len = pathsFrom.length; i < len; i += 1) {
                        GS.addLoader('file-and-folder-rename', 'Renaming Paths...');
                        intResponse = 0;
                        GS.requestFromSocket(GS.envSocket
                                           , 'FILE\tMOVE\t' + GS.encodeForTabDelimited(pathsFrom[i]) + '\t' +
                                                              GS.encodeForTabDelimited(pathsTo[i]) + '\n'
                                           , function (data, error, errorData) {
                            if (!error) {
                                if (data === 'TRANSACTION COMPLETED') {
                                    intResponse += 1;
                                    GS.removeLoader('file-and-folder-rename');

                                    if (intResponse === len) {
                                        arrCheckedPaths = [];
                                        arrCheckedPathTypes = [];
                                        listCurrentDirectory();
                                    }
                                }
                            } else if (error) {
                                intResponse += 1;
                                GS.removeLoader('file-and-folder-rename');
                                GS.webSocketErrorDialog(errorData);
                            }
                        });
                    }

                } else {
                    GS.addLoader('file-and-folder-rename', 'Renaming Paths...');
                    GS.ajaxJSON('/env/action_file', 'action=mv_file' +
                                                                '&paths_from=' + encodeURIComponent(pathsFrom) +
                                                                '&paths_to=' + encodeURIComponent(pathsTo), function(data, error) {
                        GS.removeLoader('file-and-folder-rename');

                        if (!error) {
                            arrCheckedPaths = [];
                            arrCheckedPathTypes = [];
                            listCurrentDirectory();

                        } else {
                            GS.ajaxErrorDialog(data, function() {
                                movePaths(pathsFrom, pathsTo);
                            });
                        }
                    });
                }
            }

            function deletePaths(paths) {
                'use strict';
                var i, len, intResponse;

                if (bolWebSocket) {
                    paths = JSON.parse(paths);

                    for (i = 0, len = paths.length; i < len; i += 1) {
                        GS.addLoader('file-and-folder-delete', 'Deleting Paths...');
                        intResponse = 0;
                        GS.requestFromSocket(GS.envSocket
                                           , 'FILE\tDELETE\t' + GS.encodeForTabDelimited(paths[i]) + '\n'
                                           , function (data, error, errorData) {
                            if (!error) {
                                if (data === 'TRANSACTION COMPLETED') {
                                    intResponse += 1;
                                    GS.removeLoader('file-and-folder-delete');

                                    if (intResponse === len) {
                                        arrCheckedPaths = [];
                                        arrCheckedPathTypes = [];
                                        listCurrentDirectory();
                                    }
                                }
                            } else if (error) {
                                intResponse += 1;
                                GS.removeLoader('file-and-folder-delete');
                                GS.webSocketErrorDialog(errorData);
                            }
                        });
                    }

                } else {
                    GS.addLoader('file-and-folder-delete', 'Deleting Paths...');
                    GS.ajaxJSON('/env/action_file', 'action=rm' +
                                '&paths=' + encodeURIComponent(paths), function(data, error) {
                            GS.removeLoader('file-and-folder-delete');

                            if (!error) {
                                arrCheckedPaths = [];
                                arrCheckedPathTypes = [];
                                listCurrentDirectory();

                            } else {
                                GS.ajaxErrorDialog(data, function() {
                                    deletePaths(paths);
                                });
                            }
                    });
                }
            }

            // if there is something in the query string: move that data to the correct variables
            function useQueryString() {
                var strQueryString = GS.getQueryString(), arrQSKeys = GS.qryGetKeys(strQueryString);

                bolWebSocket = true; //(GS.qryGetVal(strQueryString, 'socket') === "true");

                if (strQueryString && arrQSKeys.indexOf('path') >= 0) {
                    arrCurrentPath = GS.qryGetVal(strQueryString, 'path').split('/');
                } else {
                    arrCurrentPath = [""];
                }
            }

            window.addEventListener('popstate', function () {
                // use the query string if possible
                useQueryString();

                // get current folder
                listCurrentDirectory();
            });

            window.addEventListener('load', function (event) {
                var loadFunction, operateFunction;

                document.getElementById('current-path').addEventListener('click', function (event) {
                    this.setAttribute('hidden', '');
					document.getElementById('current-path-edit').value = this.textContent;
					document.getElementById('current-path-edit').removeAttribute('hidden');
					document.getElementById('current-path-edit').focus();
                });
                document.getElementById('current-path-edit').addEventListener('blur', function (event) {
                    GS.triggerEvent(this, 'change');
                });
                document.getElementById('current-path-edit').addEventListener('change', function (event) {
                    this.setAttribute('hidden', '');
					document.getElementById('current-path').textContent = this.value;
					document.getElementById('current-path').removeAttribute('hidden');

					arrCurrentPath = this.value.split('/');
					while (arrCurrentPath[arrCurrentPath.length - 1] === '') {
						arrCurrentPath.pop();
					}
					updateQueryString();
					listCurrentDirectory();
                });

                // use the query string if possible
                useQueryString();

                // get current folder
                listCurrentDirectory();

                // when you click on a folder button add the folder name to the array of folder
                //      names that make up the current path then refresh the list of files/folders
                document.getElementById('file-list').addEventListener('click', function (event) {
                    if (event.target.classList.contains('folder')) {
                        arrCurrentPath.push(event.target.textContent);
                        updateQueryString();
                        listCurrentDirectory();
                    }
                });

                // one of the left side checkboxes are checked add the file or folder to the array of checked paths
                //      else if the checkbox is unchecked than remove the path from the list
                document.getElementById('file-list').addEventListener('change', function (event) {
                    var path = event.target.parentNode.getAttribute('link');

                    //console.log(event.target);

                    if (event.target.value === 'true') {
                        arrCheckedPaths.push(path);
                        arrCheckedPathTypes.push(event.target.getAttribute('type'));
                    } else {
                        arrCheckedPathTypes.splice(arrCheckedPaths.indexOf(path), 1);
                        arrCheckedPaths.splice(arrCheckedPaths.indexOf(path), 1);
                    }

                    // handle toolbars disable/clearing
                    handleToolbar();
                });

                // refresh button in header
                document.getElementById('button-refresh').addEventListener('click', function (event) {
                    listCurrentDirectory();
                });

                // override CMD/CTRL - R
                window.addEventListener('keydown', function (event) {
                    var intKeyCode = event.which || event.keyCode;

                    if ((event.ctrlKey || event.metaKey) && intKeyCode === 82) {
                        event.preventDefault();
                        event.stopPropagation();
                        listCurrentDirectory();
                    }
                });


                document.getElementById('button-checked').addEventListener('click', function(event) {
                    var i, len, strHTML;

                    for (i = 0, len = arrCheckedPaths.length, strHTML = ''; i < len; i += 1) {
                        strHTML += '<div flex-horizontal>' +
                                        '<gs-checkbox inline id="checked-list-checkbox-' + i + '" value="true" ' +
                                                    'path="' + encodeHTML(arrCheckedPaths[i]) + '" ' +
                                                    'type="' + encodeHTML(arrCheckedPathTypes[i]) + '"></gs-checkbox>' +
                                        '<label for="checked-list-checkbox-' + i + '" flex>' + encodeHTML(arrCheckedPaths[i]) + '</label>' +
                                    '</div>';
                    }

                    GS.openDialog('dialog-checked-off', function () {
                        document.getElementById('checked-off-list').innerHTML = strHTML;
                        document.getElementById('checked-off-list').addEventListener('change', function (event) {
                            var path = event.target.getAttribute('path');

                            if (event.target.value === 'true') {
                                arrCheckedPaths.push(path);
                                arrCheckedPathTypes.push(event.target.getAttribute('type'));
                            } else {
                                arrCheckedPathTypes.splice(arrCheckedPaths.indexOf(path), 1);
                                arrCheckedPaths.splice(arrCheckedPaths.indexOf(path), 1);
                            }
                        });
                    }, function (event) {
                        if (event.target.textContent === 'Clear Selection') {
                            arrCheckedPaths = [];
                            arrCheckedPathTypes = [];
                        }

                        listCurrentDirectory();
                    });
                });

                document.getElementById('button-up').addEventListener('click', function(event) {
                    arrCurrentPath.pop();
                    updateQueryString();
                    listCurrentDirectory();
                });

                document.getElementById('button-top').addEventListener('click', function(event) {
                    arrCurrentPath = [""];
                    updateQueryString();
                    listCurrentDirectory();
                });

                // when the form is submitted this iframe is reloaded
                //      when it is reloaded we parse the data that is now in it looking for success
                //loadFunction =
                document.getElementById('form-response-iframe').addEventListener('load', function (event) {
                    var strResponseText = document.getElementById('form-response-iframe').contentWindow.document.body.textContent,
                        jsnResponse, strResponse, bolError, strError;

                    //console.log('1***', strResponseText);

                    // get error text
                    try {
                        jsnResponse = JSON.parse(strResponseText);

                    } catch (err) {
                        strResponse = strResponseText;
                    }

                    if (strResponse.trim() === 'Upload Succeeded') {
                        GS.closeDialog(document.getElementsByTagName('gs-dialog')[0], 'cancel');
                    } else {
                        if (jsnResponse) {
                            if (jsnResponse.stat === true) {
                                bolError = false;
                            } else {
                                bolError = true;
                                if (jsnResponse.dat && jsnResponse.dat.error) {
                                    strError = jsnResponse.dat.error;
                                } else {
                                    strError = jsnResponse.dat;
                                }
                            }
                        } else {
                            bolError = true;
                            strError = strResponse;
                        }

                        // if no error destroy new file popup
                        if (!bolError) {
                            GS.closeDialog(document.getElementsByTagName('gs-dialog')[0], 'cancel');

                        // if error open error popup
                        } else {
                            GS.msgbox('Error', strError, 'okonly');
                        }
                    }

                    arrCheckedPaths = [];
                    arrCheckedPathTypes = [];
                    listCurrentDirectory();
                    GS.removeLoader('file-upload');
                });

                document.getElementById('button-upload-file').addEventListener('click', function(event) {
                    GS.openDialog('dialog-upload', function() {
                        var loadFunction;

                        if (bolWebSocket) {
                            document.getElementById('form-file-upload').setAttribute('action', '/env/upload');
                        }

                        document.getElementById('upload-file-name').value = filePathPrefix('');

                        // upload existing file
                        document.getElementById('new-file-upload').addEventListener('click', function(event) {
                            var strFile = document.getElementById('upload-file-content').value,
                                strName = document.getElementById('upload-file-name').value;

                            if (strName === '' && strFile === '') { // no values (no file and no file path)
                                GS.msgbox('Error', 'No values in form. Please fill in the form.', 'okonly');

                            } else if (strFile === '') { // one value missing (no file)
                                GS.msgbox('Error', 'No file selected. Please select a file using the file input.', 'okonly');

                            } else if (strName === '') { // one value missing (no file path)
                                GS.msgbox('Error', 'No value in file path textbox. Please fill in file path textbox.', 'okonly');

                            } else { // values are filled in submit the form
                                document.getElementById('form-file-upload').submit();
                                GS.addLoader('file-upload', 'Uploading file...');
                            }
                        });

                        document.getElementById('upload-file-content').addEventListener('change', function(event) {
                            var strValue = this.value, uploadFileNameControl = document.getElementById('upload-file-name');

                            uploadFileNameControl.value = uploadFileNameControl.value +
                                                            strValue.substring(strValue.lastIndexOf('\\') + 1);
                            uploadFileNameControl.focus();
                        });

                        document.getElementById('upload-file-name').addEventListener('keydown', function (event) {
                            if (event.keyCode === 13) {
                                GS.triggerEvent('click', document.getElementById('new-file-upload'));
                            }
                        });
                    });
                });

                document.getElementById('button-new-file').addEventListener('click', function() {
                    GS.openDialog('dialog-create-file', function () {
                        var dialog = this, newFileNameControl = document.getElementById('new-file-name');

                        document.getElementById('new-file-name').value = filePathPrefix('');

                        // new file name focus and put cursor at specific area
                        newFileNameControl.focus();
                        GS.setInputSelection(newFileNameControl, newFileNameControl.value.length);

                        // new file name input on return: close dialog and insert file
                        newFileNameControl.addEventListener('keydown', function (event) {
                            var intKeyCode = event.which || event.keyCode;

                            if (intKeyCode === 13) {
                                GS.closeDialog(dialog, 'Ok');
                            }
                        });
                    }, function(event, strAnswer) {
                        if (strAnswer === 'Ok') {
                            insertFile(document.getElementById('new-file-name').value);
                        }
                    });
                });

                document.getElementById('button-new-folder').addEventListener('click', function () {
                    GS.openDialog('dialog-create-folder', function () {
                        var dialog = this, newFolderNameControl = document.getElementById('new-folder-name');

                        document.getElementById('new-folder-name').value = filePathPrefix('');

                        newFolderNameControl.focus();
                        GS.setInputSelection(newFolderNameControl.value.length);

                        // new file name input on return: close dialog and insert file
                        newFolderNameControl.addEventListener('keydown', function (event) {
                            var intKeyCode = event.which || event.keyCode;

                            if (intKeyCode === 13) {
                                GS.closeDialog(dialog, 'Ok');
                            }
                        });
                    }, function(event, strAnswer) {
                        if (strAnswer === 'Ok') {
                            insertFolder(document.getElementById('new-folder-name').value);
                        }
                    });
                });

                // this function has to fluidly operate across linear terrain with duo capibilities for maximum conservation of static lines
                operateFunction = function (strAction, operationFunction) {
                    document.getElementById('current-action-container').innerHTML =
                                            '<gs-grid>' +
                                            '   <gs-block><gs-button id="button-cancel">Cancel</gs-button></gs-block>' +
                                            '   <gs-block><gs-button id="button-confirm">' + strAction + ' Here</gs-button></gs-block>' +
                                            '</gs-grid>';

                    document.getElementById('button-cancel').addEventListener('click', function (event) {
                        document.getElementById('current-action-container').innerHTML = '';
                    });

                    document.getElementById('button-confirm').addEventListener('click', function (event) {
                        var i, len, arrFiles = [],
                            arrFolders = [],
                            strNewFolder = arrCurrentPath.length > 0 ? arrCurrentPath.join('/') + '/' : '',
                            strCurrentPathName,
                            strCurrentPathNameInsertIndex,
                            bolError = false;

                        document.getElementById('current-action-container').innerHTML = '';

                        // seperate files and folders
                        for (i = 0, len = arrCheckedPaths.length; i < len; i += 1) {
                            if (arrCheckedPathTypes[i] === 'file') {
                                arrFiles.push(arrCheckedPaths[i]);
                            } else {
                                arrFolders.push(arrCheckedPaths[i]);
                            }
                        }

                        // check for pasting or moving folder into itself
                        for (i = 0, len = arrFolders.length; i < len; i += 1) {
                            strCurrentPathName = '/' + GS.trim(arrFolders[i], '/') + '/';

                            if (strNewFolder.indexOf(strCurrentPathName) === 0) {
                                bolError = true;
                                GS.msgbox('Cannot ' + strAction + ' Folders',
                                          'You cannot copy a folder into itself.',
                                          ['Ok']);
                                break;
                            }
                        }

                        // if no error
                        if (!bolError) {
                            // rename files
                            for (i = 0, len = arrFiles.length; i < len; i += 1) {
                                strCurrentPathName = arrFiles[i].substring(arrFiles[i].lastIndexOf('/') + 1, arrFiles[i].length);

                                if (strNewFolder === arrFiles[i].substring(0, arrFiles[i].lastIndexOf('/') + 1) && strAction !== 'Move') {
                                    strCurrentPathNameInsertIndex = strCurrentPathName.lastIndexOf('.');

                                    strCurrentPathNameInsertIndex = strCurrentPathNameInsertIndex >= 0 ? strCurrentPathNameInsertIndex : strCurrentPathName.length;

                                    strCurrentPathName = strCurrentPathName.substring(0, strCurrentPathNameInsertIndex) + '_copy' +
                                                         strCurrentPathName.substring(strCurrentPathNameInsertIndex);
                                }

                                arrFiles[i] = strNewFolder + strCurrentPathName;
                            }

                            // rename folders
                            for (i = 0, len = arrFolders.length; i < len; i += 1) {
                                strCurrentPathName = arrFolders[i].substring(arrFolders[i].lastIndexOf('/') + 1, arrFolders[i].length);

                                if (strNewFolder === arrFolders[i].substring(0, arrFolders[i].lastIndexOf('/') + 1) && strAction !== 'Move') {
                                    strCurrentPathNameInsertIndex =
                                        strCurrentPathNameInsertIndex >= 0 ? strCurrentPathNameInsertIndex : strCurrentPathName.length;

                                    strCurrentPathName = strCurrentPathName.substring(0, strCurrentPathNameInsertIndex) + '_copy' +
                                                         strCurrentPathName.substring(strCurrentPathNameInsertIndex);
                                }

                                arrFolders[i] = strNewFolder + strCurrentPathName;
                            }

                            // operate
                            operationFunction('["' + getCheckedInOrder().join('","') + '"]', '["' + sortPathArraysInOperationOrder(arrFiles, arrFolders).join('","') + '"]');
                        }
                    });

                    document.getElementById('button-confirm').focus();
                };

                document.getElementById('button-move').addEventListener('click', function (event) {
                    operateFunction('Move', movePaths);
                });

                document.getElementById('button-copy').addEventListener('click', function (event) {
                    operateFunction('Paste', copyPaths);
                });

                document.getElementById('button-zip').addEventListener('click', function (event) {
                    GS.openDialog('dialog-download-zip', function () {
                        var dialog = this, zipNameControl = document.getElementById('text-zip-name');

                        document.getElementById('input-zip-from_paths').value = '["' + getCheckedInOrder().join('","') + '"]';

                        // new file name input on return: close dialog and insert file
                        zipNameControl.focus();
                        zipNameControl.addEventListener('keydown', function (event) {
                            var intKeyCode = event.which || event.keyCode;

                            if (intKeyCode === 13) {
                                GS.closeDialog(dialog, 'Download');
                            }
                        });
                    }, function (event, strAnswer) {
                        var form = document.getElementById('form-zip-download');

                        if (strAnswer === 'Download') {
                            form.setAttribute('action', '/env/action_file/' + document.getElementById('text-zip-name').value);
                            form.submit();
                        }
                    });
                });

                document.getElementById('button-delete').addEventListener('click', function (event) {
                    var i, len, path_i, path_len, strHTML,
                        arrCheckedSorted, arrFiles = [],
                        arrFolders = [],
                        strCurrentPath = arrCurrentPath.join('/');

                    // seperate files and folders
                    for (i = 0, len = arrCheckedPaths.length; i < len; i += 1) {
                        if (arrCheckedPathTypes[i] === 'file') {
                            arrFiles.push(arrCheckedPaths[i]);
                        } else {
                            arrFolders.push(arrCheckedPaths[i]);
                        }
                    }

                    arrCheckedSorted = sortPathArraysInOperationOrder(arrFiles, arrFolders);

                    for (i = 0, len = arrCheckedSorted.length, strHTML = ''; i < len; i += 1) {
                        strHTML += '<gs-button>' + encodeHTML(arrCheckedSorted[i]) + '</gs-button>';
                    }

                    GS.openDialog('dialog-delete', function () {
                        document.getElementById('dialog-delete-list').innerHTML = strHTML;
                    }, function(event, strAnswer) {
                        if (strAnswer === 'Yes') {
                            for (i = 0, len = arrFolders.length; i < len; i += 1) {
                                if (strCurrentPath.indexOf(arrFolders[i]) === 0) {
                                    strCurrentPath = arrFolders[i].substring(0, arrFolders[i].lastIndexOf('/'));
                                    //console.log(strCurrentPath);
                                }
                            }

                            arrCurrentPath = strCurrentPath ? strCurrentPath.split('/') : [];

                            deletePaths('["' + arrCheckedSorted.join('","') + '"]');
                        }
                    });
                });

                document.getElementById('button-rename').addEventListener('click', function(event) {
                    var i, len, strHTML, arrCheckedSorted = getCheckedInOrder(), strCurrentPath;

                    for (i = 0, len = arrCheckedSorted.length, strHTML = ''; i < len; i += 1) {
                        strCurrentPath = arrCheckedSorted[i];

                        strHTML += '<label>' + encodeHTML(strCurrentPath) + '</label>' +
                                '<gs-text class="rename-input" path-start="' + encodeHTML(strCurrentPath.substring(0, strCurrentPath.lastIndexOf('/') + 1)) +
                                        '" value="' + encodeHTML(strCurrentPath.substring(strCurrentPath.lastIndexOf('/') + 1)) + '"></gs-text>';
                    }


                    GS.openDialog('dialog-rename', function () {
                        if (arrCheckedSorted.length > 1) {
                            document.getElementById('dialog-conditional-plural').textContent = 's';
                        }

                        document.getElementById('dialog-rename-list').innerHTML = strHTML;

                    }, function (event, strAnswer) {
                        var dialog = this, arrNewPathNames = [], i, len, arrInput;

                        if (strAnswer === 'Ok') {
                            arrInput = xtag.query(dialog, '.rename-input');

                            for (i = 0, len = arrInput.length; i < len; i += 1) {
                                arrNewPathNames.push(arrInput[i].getAttribute('path-start') + arrInput[i].value);
                            }

                            renamePaths('["' + arrCheckedSorted.join('","') + '"]', '["' + arrNewPathNames.join('","') + '"]');
                        }
                    });
                });

                if (bolWebSocket) {
                    document.getElementById('button-search').setAttribute('href', 'search.html?socket=true');
                } else {
                    document.getElementById('button-search').setAttribute('href', 'search.html');
                }
            });
        </script>
        <style>
            #file-list {
                padding: 0.5em;
            }
            
            gs-checkbox {
                border-radius: 100%;
            }

            #file-list gs-button {
                text-align: left;
            }

            #file-list > h3 {
                margin-top: 0;
                margin-bottom: 0.2em;
            }

            .font-adjustment {
                font-size: 0.8em;
            }

            body > gs-page > gs-header {
                padding-bottom: 0;
                padding-left: 0.25em;
                padding-right: 0.25em;
            }

            body > gs-page > gs-footer {
                padding: 0.25em;
            }

            .spacer {
                height: 0.25em;
            }
        </style>
    </head>
    <body> <!--class="blue"-->
        <template id="dialog-checked-off">
            <gs-page>
                <gs-header><center><h3>List of files/folders that are checked off</h3></center></gs-header>
                <gs-body padded>
                    <div id="checked-off-list"></div>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>Clear Selection</gs-button></gs-block>
                        <gs-block><gs-button dialogclose listen-for-return bg-primary>Done</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <template id="dialog-upload">
            <gs-page>
                <gs-header><center><h3>Upload a File</h3></center></gs-header>
                <gs-body padded>
                    <form id="form-file-upload" action="/env/action_upload"
                          method="POST" enctype="multipart/form-data" target="form_response">
                        <label for="upload-file-content">File:</label>
                        <input type="file" id="upload-file-content" name="file_content" />
                        <br />
                        <label for="upload-file-name">File Path:</label>
                        <input id="upload-file-name" name="file_name" />
                    </form>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>Cancel</gs-button></gs-block>
                        <gs-block><gs-button id="new-file-upload">Upload File</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <template id="dialog-create-file">
            <gs-page>
                <gs-header><center><h3>Create a new File</h3></center></gs-header>
                <gs-body padded>
                    <label for="new-file-name">File name:</label>
                    <gs-text id="new-file-name"></gs-text>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>Cancel</gs-button></gs-block>
                        <gs-block><gs-button dialogclose listen-for-return bg-primary>Ok</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <template id="dialog-create-folder">
            <gs-page>
                <gs-header><center><h3>Create a new Folder</h3></center></gs-header>
                <gs-body padded>
                    <label for="new-folder-name">Folder name:</label>
                    <gs-text id="new-folder-name"></gs-text>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>Cancel</gs-button></gs-block>
                        <gs-block><gs-button dialogclose listen-for-return bg-primary>Ok</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <template id="dialog-download-zip">
            <gs-page>
                <gs-header><center><h3>Download Zip</h3></center></gs-header>
                <gs-body padded>
                    <form id="form-zip-download" method="POST" target="form_response">
                        <input hidden type="text" name="action" value="zip" />
                        <input id="input-zip-from_paths" hidden type="text" name="from_paths" />

                        <label for="text-zip-name">Name For Your Zip:</label>
                        <gs-text id="text-zip-name" value="new-zip.zip"></gs-text>
                    </form>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>Cancel</gs-button></gs-block>
                        <gs-block><gs-button dialogclose listen-for-return bg-primary>Download</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <template id="dialog-delete">
            <gs-page>
                <gs-header><center><h3>Are you sure?</h3></center></gs-header>
                <gs-body padded>
                    Are you sure that you want to delete the selected files and folders?
                    <br /><br />
                    <div id="dialog-delete-list"></div>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>No</gs-button></gs-block>
                        <gs-block><gs-button dialogclose listen-for-return bg-danger>Yes</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <template id="dialog-rename">
            <gs-page>
                <gs-header><center><h3>File / Folder Rename</h3></center></gs-header>
                <gs-body padded>
                    Change the input<span id="dialog-conditional-plural"></span> then click "Ok" to change the file / folder name
                    <br /><br />
                    <div id="dialog-rename-list"></div>
                </gs-body>
                <gs-footer>
                    <gs-grid>
                        <gs-block><gs-button dialogclose>Cancel</gs-button></gs-block>
                        <gs-block><gs-button dialogclose listen-for-return bg-primary>Ok</gs-button></gs-block>
                    </gs-grid>
                </gs-footer>
            </gs-page>
        </template>

        <gs-page>
            <gs-header>
                <div flex-horizontal>
                    <h4 id="current-path" flex>File Manager</h4>
                    <gs-text id="current-path-edit" flex hidden></gs-text>
                    <gs-button id="button-refresh" icononly icon="refresh" title="Refresh file list..." remove-right remove-margin-right></gs-button>
                    <gs-button id="button-checked" icononly icon="check" title="Look at all checked files and folders" remove-all remove-margin-horizontal disabled></gs-button>
                    <gs-button id="button-search" target="_blank" icononly icon="search" title="Go to search page..." remove-left remove-margin-left></gs-button>
                </div>
                <div class="spacer"></div>
                <div class="font-adjustment">
                    <gs-grid>
                        <gs-block><gs-button id="button-top" disabled icontop icon="angle-double-up" remove-right remove-margin-right>Top</gs-button></gs-block>
                        <gs-block><gs-button id="button-up" disabled icontop icon="angle-up" remove-all remove-margin-horizontal>Up</gs-button></gs-block>
                        <gs-block><gs-button id="button-upload-file" icontop icon="upload" remove-all remove-margin-horizontal>Upload</gs-button></gs-block>
                        <gs-block><gs-button id="button-new-file" icontop icon="plus" remove-all remove-margin-horizontal>File</gs-button></gs-block>
                        <gs-block><gs-button id="button-new-folder" icontop icon="plus" remove-left remove-margin-left>Folder</gs-button></gs-block>
                    </gs-grid>
                </div>
            </gs-header>
            <gs-body>
                <div id="file-list"></div>
            </gs-body>
            <gs-footer>
                <div class="font-adjustment">
                    <div id="current-action-container"></div>
                    <gs-grid>
                        <gs-block>
                            <gs-button id="button-zip" disabled icontop icon="download" remove-right remove-margin-right>
                                <span hide-on-desktop>Zip</span>
                                <span show-on-desktop>Download Zip</span>
                            </gs-button>
                        </gs-block>
                        <gs-block><gs-button id="button-move" disabled icontop icon="exchange" remove-all remove-margin-horizontal>Move</gs-button></gs-block>
                        <gs-block><gs-button id="button-rename" disabled icontop icon="keyboard-o" remove-all remove-margin-horizontal>Rename</gs-button></gs-block>
                        <gs-block><gs-button id="button-copy" disabled icontop icon="clipboard" remove-all remove-margin-horizontal>Copy</gs-button></gs-block>
                        <gs-block><gs-button id="button-delete" disabled icontop icon="times" remove-left remove-margin-left>Delete</gs-button></gs-block>
                    </gs-grid>
                </div>
            </gs-footer>
        </gs-page>
        <iframe src="file_form_response_target.html" id="form-response-iframe" name="form_response" hidden></iframe>
    </body>
</html>
